package cn1shared.ui;


import com.codename1.ui.Button;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Graphics;
import com.codename1.ui.Label;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.GridLayout;

import java.util.Calendar;
import java.util.Date;


public class SimpleCalendar extends Container {

	private Date selectedDate = new Date();
	private Date viewDate = new Date();
	private Label monthYearLabel;
	private final Container dayPanel;
	private ActionListener selectListener;

	private static final int DAY_TITLE_BG = 0xE5E5E5;
	private static final int SELECTED_COLOR = 0x81E690;
	private static final int[] MAX_DAYS = {31,0,31,30,31,30,31,31,30,31,30,31};
	private static final String[] MONTHS = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

	public SimpleCalendar() {
		setLayout(new BorderLayout());
		dayPanel = FormUtils.newContainer();
		monthYearLabel = FormUtils.newLabel().alignCenter().font("large-bold");

		Button btnPrevious = new Button("< Prev");
		btnPrevious.getStyle().setBgTransparency(0x00);
		btnPrevious.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				Calendar cal = Calendar.getInstance();
				cal.setTime(viewDate);
				int month = cal.get(Calendar.MONTH);
				int year = cal.get(Calendar.YEAR);
				if (month == 0) {
					month = 11;
					year--;
				} else
					month--;
				cal.set(Calendar.MONTH, month);
				cal.set(Calendar.YEAR, year);
				viewDate = cal.getTime();
				update();
			}
		});
		Button btnNext = new Button("Next >");
		btnNext.getStyle().setBgTransparency(0x00);
		btnNext.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				Calendar cal = Calendar.getInstance();
				cal.setTime(viewDate);
				int month = cal.get(Calendar.MONTH);
				int year = cal.get(Calendar.YEAR);
				if (month == 11) {
					month = 0;
					year++;
				} else
					month++;
				cal.set(Calendar.MONTH, month);
				cal.set(Calendar.YEAR, year);
				viewDate = cal.getTime();
				update();
			}
		});

		Container topPanel = FormUtils.newContainer(new BorderLayout());
		topPanel.addComponent(BorderLayout.CENTER, monthYearLabel);
		topPanel.addComponent(BorderLayout.WEST, btnPrevious);
		topPanel.addComponent(BorderLayout.EAST, btnNext);

		addComponent(BorderLayout.NORTH, topPanel);
		addComponent(BorderLayout.CENTER, dayPanel);
		update();
	}

	public void setDate(Date date) {
		this.selectedDate = new Date(date.getTime());
		this.viewDate =new Date(date.getTime());
		update();
	}

	public Date getSelectedDate() {
		return selectedDate;
	}

	public void setSelectListener(ActionListener listener) {
		this.selectListener = listener;
	}

	private void update() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(selectedDate);
		final int selectedDay = cal.get(Calendar.DAY_OF_MONTH);
		int selectedMonth = cal.get(Calendar.MONTH);
		int selectedYear = cal.get(Calendar.YEAR);

		cal.setTime(new Date());
		int today = cal.get(Calendar.DAY_OF_MONTH);
		int currentMonth = cal.get(Calendar.MONTH);
		int currentYear = cal.get(Calendar.YEAR);

		cal.setTime(viewDate);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		int firstDay = cal.get(Calendar.DAY_OF_WEEK);
		int month = cal.get(Calendar.MONTH);
		int year = cal.get(Calendar.YEAR);
		int nDays = getNumberOfDays(month, year);

		monthYearLabel.setText(MONTHS[month] + ' ' + year);

		dayPanel.removeAll();
		int rowCount = (int) Math.ceil((7 + firstDay + nDays) / 7.0);
		dayPanel.setLayout(new GridLayout(rowCount, 7));

		dayPanel.addComponent(FormUtils.newLabel("Su").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());
		dayPanel.addComponent(FormUtils.newLabel("Mo").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());
		dayPanel.addComponent(FormUtils.newLabel("Tu").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());
		dayPanel.addComponent(FormUtils.newLabel("We").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());
		dayPanel.addComponent(FormUtils.newLabel("Th").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());
		dayPanel.addComponent(FormUtils.newLabel("Fr").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());
		dayPanel.addComponent(FormUtils.newLabel("Sa").font("large-bold").alignCenter().background(DAY_TITLE_BG).noDots());

		ActionListener listener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				Button btn = (Button) evt.getComponent();
				int day = Integer.valueOf(btn.getText());
				Calendar cal = Calendar.getInstance();
				cal.setTime(viewDate);
				cal.set(Calendar.DAY_OF_MONTH, day);
				selectedDate = cal.getTime();
				if (selectListener != null)
					selectListener.actionPerformed(new ActionEvent(null));
			}
		};

		for (int i = 1; i < firstDay; i++) {
			dayPanel.addComponent(FormUtils.newLabel());
		}
		int d = 1;
		while (d <= nDays) {
			Button btn;
			boolean isToday = d == today && month == currentMonth && year == currentYear;
			if (isToday) {
				btn = new Button(String.valueOf(d)) {
					@Override
					public void paint(Graphics g) {
						super.paint(g);
						// some crazy math to underline the number
						int halfw = Math.round(0.7f * g.getFont().stringWidth(this.getText()));
						int halfh = Math.round(0.5f * g.getFont().getHeight());
						int mx = getX() + getWidth()/2;
						int my = getY() + getHeight()/2;
						g.setColor(getStyle().getFgColor());
						g.fillRect(mx - halfw, my + halfh + halfh/2, 2 * halfw, 3);
					}
				};
				btn.setVerticalAlignment(Component.TOP);
			} else
				btn = new Button(String.valueOf(d));

			btn.addActionListener(listener);
			dayPanel.addComponent(btn);

			if (d == selectedDay && month == selectedMonth && year == selectedYear) {
				btn.getStyle().setBgColor(SELECTED_COLOR);
				btn.getStyle().setBgTransparency(0xFF);
			} else
				btn.getStyle().setBgTransparency(0x00);
			d++;
		}
		revalidate();
	}

	private int getNumberOfDays(int month, int year) {
		if (month == 1) { // February
			boolean isLeap = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
			return isLeap? 29 : 28;
		}
		return MAX_DAYS[month];
	}

}
